const assert = require('assert');
const { constants, expectEvent } = require('@openzeppelin/test-helpers');
exports.detail = () => {
    it('代币名称: name()', async function() {
        assert.equal(ERC721Param[0], await ERC721Instance.name());
    });
    it('代币缩写: symbol()', async function() {
        assert.equal(ERC721Param[1], await ERC721Instance.symbol());
    });
    it('代币基本地址: baseURI()', async function() {
        assert.equal(ERC721Param[2], await ERC721Instance.baseURI());
    });
    it('合约实现接口: supportsInterface()', async function() {
        assert.ok(await ERC721Instance.supportsInterface('0x80ac58cd'));
    });
}

//测试代币方法
exports.awardItem = (account,uri,desc,reject,msg) => {
    it(desc + ': awardItem()', async function() {
        if(reject) {
            await assert.rejects(ERC721Instance.awardItem(account,uri,{from:account}), msg);
        } else {
            const receipt = await ERC721Instance.awardItem(account, uri, {from:account});
            expectEvent(receipt, 'Transfer', {
                from: constants.ZERO_ADDRESS,
                to: account,
            });
        }
    });
}

//测试代币总量
exports.totalSupply = (totalSupply) => {
    it('代币总量: totalSupply()', async function() {
        assert.equal(totalSupply, (await ERC721Instance.totalSupply()).toString());
    });
}

//测试账户余额
exports.balanceOf = (balance,account,desc,reject,msg) => {
    it(desc + ':balanceOf()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.balanceOf(account), msg);
        } else {
            assert.equal(balance, await ERC721Instance.balanceOf(account));
        }
    });
}

//批准全部代币
exports.setApprovalForAll = (owner, operator, desc, reject, msg) => {
    it(desc + ':setApprovalForAll()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.setApprovalForAll(receiver,true, {from:receiver}), msg);
        } else {
            let receipt = await ERC721Instance.setApprovalForAll(operator, true, {from:owner});
            expectEvent(receipt,'ApprovalForAll', {
                owner: owner,
                operator: operator,
                approved: true
            });
        }
    });
}

//验证代币全部被批准
exports.isApprovedForAll = (owner,operator,desc) => {
    it(desc + ':isApprovedForAll()', async function() {
        assert.ok(await ERC721Instance.isApprovedForAll(owner,operator));
    });
}

//根据账户的代币索引，获取代币ID
exports.tokenOfOwnerByIndex = (owner,index,desc,reject,msg) => {
    it(desc + ':tokenOfOwnerByIndex()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.tokenOfOwnerByIndex(owner,index), msg);
        } else {
            tokenId = await ERC721Instance.tokenOfOwnerByIndex(owner,index);
        }
    });
}

//根据代币索引获取代币id
exports.tokenByIndex = (index,_tokenId,desc,reject,msg) => {
    it(desc + ':tokenByIndex()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.tokenByIndex(index), msg);
        } else if(_tokenId){
            assert.equal(_tokenId,await ERC721Instance.tokenByIndex(index));
        } else {
            assert.equal(tokenId, await ERC721Instance.tokenByIndex(index));
        }
    });
}

//根据tokenID验证账户地址
exports.ownerOf = (owner,_tokenId,desc,reject,msg) => {
    it(desc + ':ownerOf()', async function() {
        if (_tokenId) {
            await assert.rejects(ERC721Instance.ownerOf(_tokenId), msg);
        } else if(reject){
            await assert.rejects(ERC721Instance.ownerOf(tokenId),msg);
        } else {
            assert.equal(owner,await ERC721Instance.ownerOf(tokenId));
        }
    });
}

//验证tokenURI
exports.tokenURI = (tokenURI,_tokenId,desc,reject,msg) => {
    it(desc + ':tokenURI()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.tokenURI(_tokenId), msg);
        } else if(_tokenId) {
            assert.equal(tokenURI,await ERC721Instance.tokenURI(_tokenId));
        } else {
            assert.equal(tokenURI,await ERC721Instance.tokenURI(tokenId));
        }
    });
}

//批准代币
exports.approve = (to,owner,_tokenId, desc, reject, msg) => {
    it(desc + ':approve()', async function() {
        if (_tokenId) {
            await assert.rejects(ERC721Instance.approve(to,_tokenId,{from:owner}), msg);
        } else if(reject) {
            await assert.rejects(ERC721Instance.approve(to, tokenId, { from: owner }), msg);
        } else {
            let receipt = await ERC721Instance.approve(to, tokenId,{from:owner});
            expectEvent(receipt,'Approval', {
                owner: owner,
                approved: sender,
                tokenId: tokenId
            });
        }
    });
}

//获取代币批准的地址
exports.getApproved = (sender,_tokenId,desc,reject,msg) => {
    it(desc + ':getApproved()', async function() {
        if (_tokenId) {
            await assert.rejects(ERC721Instance.getApproved(_tokenId), msg);
        } else if (reject){
            await assert.rejects(ERC721Instance.getApproved(tokenId), msg);
        } else {
            assert.equal(sender, await ERC721Instance.getApproved(tokenId));
        }
    });
}

//批准发送
exports.transferFrom = (sender,from,to,_tokenId,desc,reject,msg) => {
    it(desc + ':transferFrom()', async function() {
        if (_tokenId) {
            await assert.rejects(ERC721Instance.transferFrom(from,to,_tokenId, {from:sender}), msg);
        } else if(reject) {
            await assert.rejects(ERC721Instance.transferFrom(from,to, tokenId, {from:sender}), msg);
        } else {
            let receipt = await ERC721Instance.transferFrom(from,to,tokenId,{from:sender});
            expectEvent(receipt,'Transfer',{
                from:from,
                to:to,
                tokenId: tokenId
            });
        }
    });
}

//批准安全发送
exports.safeTransferFrom = (sender,from,to,_tokenId,desc,reject,msg) => {
    it(desc + ':safeTransferFrom()', async function() {
        if (_tokenId) {
            await assert.rejects(ERC721Instance.safeTransferFrom(from,to,_tokenId, {from:sender}), msg);
        } else if(reject) {
            await assert.rejects(ERC721Instance.safeTransferFrom(from,to, tokenId, {from:sender}), msg);
        } else {
            let receipt = await ERC721Instance.safeTransferFrom(from,to,tokenId,{from:sender});
            expectEvent(receipt,'Transfer',{
                from:from,
                to:to,
                tokenId: tokenId
            });
        }
    });
}

//添加暂停管理员
exports.addMinter = (minter,sender,desc,reject,msg) => {
    it(desc + ':addMinter()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.addMinter(minter,{from:sender}), msg);
        } else {
            let receipt = await ERC721Instance.addMinter(minter,{from:sender});
            expectEvent(receipt,'MinterAdded', {
                account:minter
            });
        }
    });
}

//测试账户是否拥有暂停权
exports.isMinter = (minter,isMinter,desc) => {
    it(desc + ':isMinter()', async function() {
        assert.equal(isMinter, await ERC721Instance.isMinter(minter));
    });
}

//测试撤销暂停管理员
exports.renounceMinter = (minter,desc,reject,msg) => {
    it(desc + ':renounceMinter()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.renounceMinter({from:minter}), msg);
        } else {
            let receipt = await ERC721Instance.renounceMinter({from:minter});
            expectEvent(receipt,'MinterRemoved', {
                account: minter
            });
        }
    });
}

//铸币方法
exports.mint = (minter,to,_tokenId,desc,reject,msg) => {
    it(desc + ':mint()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.mint(to,_tokenId,{from:minter}), msg);
        } else {
            let receipt = await ERC721Instance.mint(to,_tokenId,{from:minter});
            expectEvent(receipt, 'Transfer', {
                from: constants.ZERO_ADDRESS,
                to: to,
                tokenId: _tokenId
            });
        }
    });
}

//安全铸币方法
exports.safeMint = (minter,to, _tokenId, desc,reject, msg) => {
    it(desc + ':mint()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.mint(to,_tokenId,{from:minter}), msg);
        } else {
            let receipt = await ERC721Instance.mint(to,_tokenId,{from:minter});
            expectEvent(receipt,'Transfer', {
                from:constants.ZERO_ADDRESS,
                to: to,
                tokenId: _tokenId
            });
        }
    });
}

//待URI铸币方法
exports.mintWithTokenURI = (minter,to,uri,_tokenId,desc,reject,msg) => {
    it(desc + ':mintWithTokenURI()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.mintWithTokenURI(to,_tokenId,uri,{from:minter}),msg);
        } else {
            let receipt = await ERC721Instance.mintWithTokenURI(to,_tokenId,uri,{from:minter});
            expectEvent(receipt, 'Transfer', {
                from: constants.ZERO_ADDRESS,
                to: to,
                tokenId: _tokenId
            });
        }
    });
}

//测试销毁方法
exports.burn = (owner,_tokenId,desc,reject,msg) => {
    it(desc + ':burn()', async function() {
        let receipt;
        if (reject) {
            if (_tokenId) {
                await assert.rejects(ERC721Instance.burn(_tokenId,{from:owner}), msg);
            } else {
                await assert.rejects(ERC721Instance.burn(tokenId,{from:owner}), msg);
            }
        } else {
            if (_tokenId) {
                receipt = await ERC721Instance.burn(_tokenId, {from:owner});
                expectEvent(receipt,'Transfer',{
                    from:owner,
                    to:constants.ZERO_ADDRESS,
                    tokenId: _tokenId
                });
            } else {
                receipt = await ERC721Instance.burn(tokenId,{from:owner});
                expectEvent(receipt,'Transfer', {
                    from:owner,
                    to: constants.ZERO_ADDRESS,
                    tokenId: tokenId,
                });
            }
        }
    });
}

//添加暂停管理员
exports.addPauser = (pauser,sender,desc,reject,msg) => {
    it(desc + ':addPauser()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.addPauser(pauser,{from:sender}), msg);
        } else {
            let receipt = await ERC721Instance.addPauser(pauser,{from:sender});
            expectEvent(receipt, 'PauserAdded', {
                account:pauser
            });
        }
    });
}

//测试账户是否暂停权
exports.isPauser = (pauser,isPauser,desc) => {
    it(desc + ':isPauser()', async function() {
        assert.equal(isPauser, await ERC721Instance.isPauser(pauser));
    });
}

//测试撤销暂停管理员
exports.renouncePauser = (pauser,desc,reject,msg) => {
    it(desc + ':renouncePauser()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.renouncePauser({from:pauser}), msg);
        } else {
            let receipt = await ERC721Instance.renouncePauser({from:pauser});
            expectEvent(receipt,'PauserRemoved',{
                account: pauser
            });
        }
    });
}

//测试是否已经暂停
exports.paused = (paused,desc) => {
    it(desc+':paused()', async function(){
        assert.equal(paused,await ERC721Instance.paused());
    });
}

//测试撤销暂停管理员
exports.pause = (pauser,desc,reject,msg) => {
    it(desc + ':pause()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.pause({from:pauser}), msg);
        } else {
            let receipt = await ERC721Instance.pause({from:pauser});
            expectEvent(receipt,'Paused',{
                account: pauser
            });
        }
    });
}

//测试恢复合约
exports.unpause = (pauser,desc,reject,msg) => {
    it(desc + ':unpause()', async function() {
        if (reject) {
            await assert.rejects(ERC721Instance.unpause({from:pauser}), msg);
        } else {
            let receipt = await ERC721Instance.unpause({from:pauser});
            expectEvent(receipt,'Unpaused', {
                account: pauser
            });
        }
    });
}
